package com.dhz.common.solr;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;

import java.io.Serializable;
import java.util.Collection;

/**
 * <p>该接口统一指定一组Solr的操作，有template自定义实现方式, 如：{@link SolrTemplate}</p>
 * <p>现在支持的方法还比较少，需完善</p>
 *
 * @author Fyduan
 */
public interface SolrOperations {

    /**
     * 获得一个SolrClient实例
     * @return {@link SolrClient}
     */
    SolrClient getSolrClient();

    /**
     * 在一个{@link SolrClient} 实例上执行一次ping操作，返回往返时长
     * @return {@link SolrPingResponse}
     */
    SolrPingResponse ping();

    /**
     * 根据查询条件，返回符合条件的数据总数
     * @param query {@link SolrQuery} 查询参数
     * @return 返回数量
     */
    long count(SolrQuery query);

    /**
     * 在Solr上执行添加操作，可以是更新或插入
     * @param object {@link Object} 数据对象
     * @return 操作结果
     */
    // 尚未实现，不启用
    // UpdateResponse saveBean(Object object);

    /**
     * 在Solr上执行添加操作，可以是更新或插入；同时必须在指定的时间内完成，否则该操作失败;
     * @param object 数据对象
     * @param commitWithInMs 操作事时限，单位：毫秒
     * @return 操作结果
     */
    // 尚未实现，不启用
    // UpdateResponse saveBean(Object object, int commitWithInMs);

    /**
     * 添加一个集合数据到Solr，可以是更新或插入；
     * @param beans {@link Collection} 数据集合
     * @return 操作结果
     */
    // 尚未实现，不启用
    // UpdateResponse saveBeans(Collection<?> beans);


    /**
     * 添加一个集合数据到Solr，可以是更新或插入；同时必须在指定的时间内完成，否则该操作失败;
     * @param beans {@link Collection} 数据集合
     * @param commitWithInMs 操作事时限，单位：毫秒
     * @return 操作结果
     */
    // 尚未实现，不启用
    // UpdateResponse saveBeans(Collection<?> beans, int commitWithInMs);

    /**
     * 添加一个solrj的{@link SolrInputDocument} 文档数据到solr，可以是更新或插入；
     * @param doc {@link SolrInputDocument} 文档对象数据
     * @return 操作结果
     */
    UpdateResponse saveDoc(SolrInputDocument doc);

    /**
     * 添加一个solrj的{@link SolrInputDocument} 文档数据到solr，可以是更新或插入；同时必须在指定的时间内完成，否则该操作失败;
     * @param doc {@link SolrInputDocument} 文档对象数据
     * @param commitWithInMs 操作事时限，单位：毫秒
     * @return 操作结果
     */
    UpdateResponse saveDoc(SolrInputDocument doc, int commitWithInMs);

    /**
     * 添加多个solrj的{@link SolrInputDocument} 文档数据到solr，可以是更新或插入；
     * @param docs {@link Collection} 文档对象数据
     * @return 操作结果
     */
    UpdateResponse saveDocs(Collection<SolrInputDocument> docs);

    /**
     * 添加多个solrj的{@link SolrInputDocument} 文档数据到solr，可以是更新或插入；同时必须在指定的时间内完成，否则该操作失败;
     * @param docs {@link Collection} 文档对象数据
     * @param commitWithInMs 操作事时限，单位：毫秒
     * @return 操作结果
     */
    UpdateResponse saveDocs(Collection<SolrInputDocument> docs, int commitWithInMs);

    /**
     * 删除所有符合查询条件的记录
     * @param query {@link SolrQuery} 查询参数
     * @return 操作结果
     */
    UpdateResponse delete(SolrQuery query);

    /**
     * 根据ID删除记录
     * @param id ID
     * @return 操作结果
     */
    UpdateResponse deleteById(String id);

    /**
     * 根据ID集合删除记录
     * @param ids {@link Collection} Id集合
     * @return 操作结果
     */
    UpdateResponse deleteById(Collection<String> ids);

    /**
     * 根据ID获得记录数据
     * @param id ID
     * @param clazz 传入返回类型Class
     * @param <T> 返回类型
     * @return 返回数据
     */
    // 尚未实现，暂不启用
    <T> T getById(Serializable id, Class<T> clazz);

    /**
     * 根据ID集合获取数据
     * @param ids {@link Collection} ID集合
     * @return 集合数据
     */
    // 尚未实现，暂不启用
    <T> Collection<T> getById(Collection<? extends Serializable> ids, Class<T> clazz);

    /**
     * 根据查询参数到solr获得结果，并返回第一个数据
     * @param query {@link SolrQuery} solrj 的查询参数封装；后期会加入自己封装
     * @param clazz 传入返回类型Class
     * @param <T> 返回类型
     * @return 返回数据
     */
    // 尚未实现，暂不启用
    <T> T queryForObject(SolrQuery query, Class<T> clazz);

    /**
     * 根据查询参数到solr获得结果，并返回第一个数据
     * @param query {@link SolrQuery} solrj 的查询参数封装；后期会加入自己封装
     * @return {@link SolrDocument}
     */
    SolrDocument queryForSolrDoc(SolrQuery query);

    /**
     * 根据查询参数到solr获得结果, 主要用于分页查询
     * @param query {@link SolrQuery} solrj 的查询参数封装；后期会加入自己封装
     * @return {@link SolrDocumentList}
     */
    SolrDocumentList queryForSolrDocs(SolrQuery query);

    // ------
    // 待完善的操作，如分页查询等
    // ------

    /**
     * 发送commit命令， {@link SolrClient#commit()}
     */
    void commit();

    /**
     * 发送soft commit命令， {@link SolrClient#commit(boolean, boolean, boolean)}
     */
    void softCommit();

    /**
     * 发送回滚命令， {@link SolrClient#rollback()}
     */
    void rollback();

    /**
     * 转换JavaBean对象为可供solrj直接使用的{@link SolrInputDocument}
     * @param bean bean数据
     * @return {@link SolrInputDocument}
     */
    // SolrInputDocument convertBeanToSolrInpDoc(Object bean);

    /**
     * 使用回调执行操作
     * @param callback {@link SolrCallback} 回调实现
     * @param <T> 返回数据类型
     * @return 操作结果
     */
    <T> T execute(SolrCallback<T> callback);

}
